﻿/*******************************************************************************
 * AAEngine
 * Copyright (c) 2010 Mike Jarosch
 *
 * Original source PushButton Engine:
 * Copyright (C) 2009 PushButton Labs, LLC
 * For more information see http://www.pushbuttonengine.com
 *
 * This file is licensed under the terms of the MIT license, which is included
 * in the "MIT License.txt" file at the root directory of this SDK.
 ******************************************************************************/

using System.Collections.Generic;
using Microsoft.Xna.Framework;
using AAEngine.Engine;
using AAEngine.Engine.Core;

namespace AAEngine.Rendering2D
{
    /// <summary>
    /// Basic interface for 2D spatial database.
    /// 
    /// This provides enough capabilities to do visibility culling, limited picking,
    /// and ray casts.
    /// 
    /// Most implementations (like ones using a physics library) will expose a
    /// lot more functionality, but this is enough to do rendering and UI tasks.
    /// </summary>
    public interface ISpatialManager2D
    {
        /// <summary>
        /// Add a generic spatial object to this manager. A manager with advanced
        /// functionality will support both general ISpatialObject2D implementations
        /// as well as enabling special functionality for its peered classes.
        /// </summary>
        void AddSpatialObject(ISpatialObject2D spatialObject);

        /// <summary>
        /// Remove a previously registered object from this manager.
        /// </summary>
        void RemoveSpatialObject(ISpatialObject2D spatialObject);

        /// <summary>
        /// Return all the spatial objects that overlap with the specified box and match
        /// one or more of the types in the mask.
        /// </summary>
        /// <remarks>
        /// Note that if you pass in a populated array, this method appends to it.
        /// This can be useful if you want to combine the results of several
        /// queries. If you just want the results from one query, make sure to
        /// set results.Clear(); before you pass it to QueryRectangle.
        /// </remarks>
        /// <param name="box">Rectangle in worldspace to check.</param>
        /// <param name="mask">Only consider objects that match this ObjectType. Null uses all types.</param>
        /// <param name="results">An array into which ISpatialObject2Ds are added.</param>
        /// <returns>True if one or more objects were found and Add()'ed to results.</returns>
        bool QueryRectangle(Box box, ObjectType mask, ref IList<ISpatialObject2D> results);

        /// <summary>
        /// Return all the spatial objects that overlap the specified circle.
        /// </summary>
        /// <remarks>
        /// Note that if you pass in a populated array, this method appends to it.
        /// This can be useful if you want to combine the results of several
        /// queries. If you just want the results from one query, make sure to
        /// set results.Clear(); before you pass it to QueryRectangle.
        /// </remarks>
        /// <param name="center">Center of circle in worldspace to check.</param>
        /// <param name="radius">Size of circle in worldspace to check.</param>
        /// <param name="mask">Only consider objects that match this ObjectType. Null uses all types.</param>
        /// <param name="results">An array into which ISpatialObject2Ds are added.</param>
        /// <returns>True if one or more objects were found and Add()'ed to results.</returns>
        bool QueryCircle(Vector2 center, int radius, ObjectType mask, ref IList<ISpatialObject2D> results);

        /// <summary>
        /// Return all the spatial objects under a given point.
        /// </summary>
        /// <remarks>
        /// Note that if you pass in a populated array, this method appends to it.
        /// This can be useful if you want to combine the results of several
        /// queries. If you just want the results from one query, make sure to
        /// set results.Clear(); before you pass it to QueryRectangle.
        /// </remarks>
        /// <param name="point">Point in worldspace to check.</param>
        /// <param name="mask">Only consider objects that match this ObjectType. Null uses all types.</param>
        /// <param name="results">An array into which ISpatialObject2Ds are added.</param>
        /// <returns>True if one or more objects were found and Add()'ed to results.</returns>
        bool QueryPoint(Vector2 point, ObjectType mask, ref IList<ISpatialObject2D> results);

        /// <summary>
        /// Cast a ray and (optionally) return information about what it hits in result.
        /// </summary>
        /// <returns></returns>
        bool CastRay(Vector2 start, Vector2 end, ObjectType mask, ref RayHitInfo result);
    }
}
